package com.glink.manage.controller;

import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.glink.common.exception.GeneralSimpleException;
import com.glink.common.util.BaseCommonUtils;
import com.glink.common.util.LogUtil;
import com.glink.common.vo.ResponseResult;
import com.glink.manage.common.CommonUtils;
import com.glink.manage.common.JwtUtil;
import com.glink.manage.dto.user.*;
import com.glink.manage.service.PasswordService;
import com.glink.manage.service.SecurityService;
import com.glink.manage.vo.security.FindCryptoReq;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * Created by IntelliJ IDEA.
 *
 * @Author : qiushaoshan
 * @create 2024/6/17 17:29
 */
@Slf4j
@RestController
@RequestMapping("/API/Manage/security")
@Api(tags = "安全管理")
public class SecurityController extends AbstractBaseController {
    
    @Autowired
    private SecurityService securityService;
    
    @Autowired
    private PasswordService passwordService;
    
    @ApiOperationSupport(order = 0)
    @ApiOperation(value = "00.测试加密(SM2),此接口客户端不调用,测试使用")
    @PostMapping(path = "/encryptBySm2", produces = MediaType.APPLICATION_JSON_UTF8_VALUE, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseResult<String> encryptBySm2(@Validated @RequestBody EncryptBySm2DTO encryptBySm2DTO) throws Exception {
        log.info("01.测试加密(SM2),此接口客户端不调用,测试使用 random[{}] userName[{}] plain[{}]", encryptBySm2DTO.getRandom(), encryptBySm2DTO.getUserName(), encryptBySm2DTO.getPwd());
        String publicKey = securityService.findOnePublicKey(encryptBySm2DTO.getUserName());
        String cipher = passwordService.encrypt(publicKey, encryptBySm2DTO.getRandom() + encryptBySm2DTO.getPwd());
        return this.response(cipher);
    }

    @ApiOperation(value = "00.测试解密(SM2),此接口客户端不调用,测试使用")
    @PostMapping(path = "/onlyDecryptAndRemoveKeyBySm2", produces = MediaType.APPLICATION_JSON_UTF8_VALUE, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ApiOperationSupport(order = 0)
    public ResponseResult<String> onlyDecryptAndRemoveKeyBySm2(@Validated @RequestBody CipherDTO vo) throws Exception {
        log.info("02.测试解密(sm2) 密文 {}", vo);
        String privateKey = securityService.findOnePrivateKey(vo.getAccount());

        String result = passwordService.onlyDecryptAndRemoveKey(privateKey, vo.getCipher());
        return this.response(result);
    }
    
    @ApiOperationSupport(order = 1)
    @ApiOperation(value = "01.（第二步）查询你的加密公钥Key", notes = "1.查询你的加密公钥Key")
    @PostMapping(value = "/crypto/findYourKey", produces = MediaType.APPLICATION_JSON_UTF8_VALUE, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseResult<String> insertOrModifyUser(@RequestBody @Validated FindCryptoReq findCryptoReq) throws GeneralSimpleException {
        log.info("1.查询你的加密公钥Key：{}", LogUtil.encode(findCryptoReq));
        String publicKey = securityService.findOnePublicKey(findCryptoReq.getUserName());
        return this.response(publicKey);
    }

    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "02.（第一步）获得随机Key")
    @GetMapping(path = "/crypto/randomKey", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseResult<List<String>> randomKey() {
        log.info("02.获得随机Key");
        List<String> keys = securityService.randomKey();
        log.info("02.获得随机Key {}", keys);
        return this.response(keys);
    }

    @ApiOperationSupport(order = 3)    
    @ApiOperation(value = "03.（第三步）生成Token（用密钥加密后的密码）")
    @PostMapping(path = "/generateToken", produces = MediaType.APPLICATION_JSON_UTF8_VALUE, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseResult<String> generateToken(@Validated @RequestBody LoginDTO loginDTO, HttpServletRequest request) throws Exception {
        String remoteIp = BaseCommonUtils.getIP(request);
        log.info("03.生成Token {}  ,ip {}", loginDTO, remoteIp);
        String result = securityService.generateToken(loginDTO, remoteIp);
        return this.response(result);
    }

    @ApiOperationSupport(order = 4)
    @ApiOperation(value = "04.注销Token")
    @GetMapping(path = "/logout")
    @ApiImplicitParam(paramType = "header", name = "Authorization", value = "jwtToken,必须是以 Bearer 开始(注意 Bearer后有一个英文空格)", dataType = "string", required = true)
    public ResponseResult<String> logout(HttpServletRequest request) throws Exception {
        String remoteIp = BaseCommonUtils.getIP(request);
        String jwtToken = JwtUtil.getJwtTokenFromRequest(request);
        log.info("5.注销Token {}", jwtToken);
        securityService.logout(jwtToken, remoteIp);
        return this.response(null);
    }

    @ApiOperation(value = "05.获取Token剩余有效时间")
    @RequestMapping(path = "/API/AI-Platform-SSO/secure/validTime", method = RequestMethod.GET)
    @ApiOperationSupport(order = 5)
    @ApiImplicitParam(paramType = "header", name = "Authorization", value = "jwtToken,必须是以 Bearer 开始(注意 Bearer后有一个英文空格)", dataType = "string", required = true)
    public ResponseResult<Long> validTime(HttpServletRequest request) throws Exception {
        String jwtToken = JwtUtil.getJwtTokenFromRequest(request);
        log.info("04.获取Token剩余有效时间 {}", jwtToken);
        return this.response(securityService.validTime(jwtToken));
    }

    @ApiOperationSupport(order = 6)
    @ApiOperation(value = "06.修改密码(无token)", notes = "06.修改密码(无token)")
    @PostMapping(value = "/updatePwd", produces = MediaType.APPLICATION_JSON_UTF8_VALUE, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseResult<Boolean> updatePwd(@RequestBody @Validated UserUpdatePwdDTO pwdDTO) throws GeneralSimpleException {
        log.info("06.修改密码(无token)：{}", LogUtil.encode(pwdDTO));
        Boolean status = securityService.updatePwd(pwdDTO);
        log.info("06.修改密码(无token)：success");
        return this.response(status);
    }

    @ApiOperationSupport(order = 7)
    @ApiOperation(value = "07.重置密码")
    @PostMapping(path = "/restPwd", produces = MediaType.APPLICATION_JSON_UTF8_VALUE, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ApiImplicitParam(paramType = "header", name = "userId", value = "当前登录用户的用户id", dataType = "string", required = true)
    public ResponseResult<Boolean> restPasswd(@Validated @RequestBody UserRestPwdDTO restPwdDTO) throws Exception {
        log.info("02.重置密码{}", LogUtil.encode(restPwdDTO));
        String userId = CommonUtils.extractUserIdtByToken();
        Boolean status = securityService.restPasswd(restPwdDTO, userId);
        log.info("02.重置密码");
        return this.response(status);
    }

    @ApiOperationSupport(order = 8)
    @ApiOperation(value = "08.修改密码(带token)", notes = "08.修改密码(带token)")
    @ApiImplicitParam(paramType = "header", name = "userId", value = "当前登录用户的用户id", dataType = "string", required = true)
    @PostMapping(value = "/updatePwd2", produces = MediaType.APPLICATION_JSON_UTF8_VALUE, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseResult<Boolean> updatePwd2(@RequestBody @Validated UserUpdatePwd2DTO pwdDTO) throws GeneralSimpleException {
        log.info("06.修改密码(带token)：{}", LogUtil.encode(pwdDTO));
        String userId = CommonUtils.extractUserIdtByToken();
        Boolean status = securityService.updatePwd2(userId, pwdDTO);
        log.info("06.修改密码(带token)：success");
        return this.response(status);
    }
}
